

#include <gtk/gtk.h>
#include <stdio.h>
#include "support.h"
#include "config.h"
#include "memview.h"
#include "codeview.h"
#include "statusbar.h"
#include "window.h"
#include "memfill_call.h"
#include "memfill.h"
#include "memfill_table.h"
#include "page_state.h"
#include "keypad.h"
#include "dialog.h"

/*############## Globals #################*/
gchar *address;
gchar *op1;
gchar *op2;
GObject *gsim_label_address;    /*for label-addr pairs*/

/*############## Return int from a string ##############*/
gint make_int__(const gchar *str)
{
	gint i;
	sscanf(str,"%X",&i);
	return i;
}

/*############# Return a string from int #############*/
gchar *make_str__(gint i,gint width)
{
	static gchar x[5];
	switch(width)
	{
		case 4: snprintf(x,5,"%04X",i); break;
			case 2: snprintf(x,5,"%02X",i); break;
				case 1: snprintf(x,5,"%01X",i); break;
	}
	return x;
}

/*################### Update the memory(fill memview) ####################*/
void gsim_update_memory(void)
{
	gchar *current_address=NULL;
	gchar *mne;
	gchar *label;
	gboolean is_iter;
	
	/*no line in the code*/
	if(!gtk_tree_model_get_iter_first(current_code_model,&current_code_iter))
		return;
	
	GObject *label_addr_pair;
	label_addr_pair=g_object_new(G_TYPE_OBJECT,NULL);
	gsim_label_address=label_addr_pair;  /*to make global for functions in memfill_call.c*/

	/*iterate from 1st to last line*/
	for(is_iter=gtk_tree_model_get_iter_first(current_code_model,&current_code_iter); is_iter ;
									is_iter=gtk_tree_model_iter_next(current_code_model,&current_code_iter))
	{
		/*get the line data*/
		gtk_tree_model_get(current_code_model,&current_code_iter,ADDR_COL,&address,LABEL_COL,&label,
								MNE_COL,&mne,OP1_COL,&op1,OP2_COL,&op2,-1);
		
		/*line is empty means new section is started*/
		if(!mne)
		{
			current_address=NULL;
			g_free(address);
			g_free(mne);
			g_free(op1);
			g_free(op2);
			g_free(label);
			continue;
		}
		
		/*check if adress of first line of section provided*/		
		if(!current_address)
		{
			if(!g_strcasecmp(address,"")) /*not provided*/
			{
				remove_marker();
				scroll_to_row();
				gsim_message(_("Provide start address of the new section."),GTK_MESSAGE_ERROR);
				/*free any resources*/
				g_free(address);
				g_free(mne);
				g_free(op1);
				g_free(op2);
				g_free(label);
				g_object_unref(label_addr_pair);
				gsim_label_address=NULL;
				return;
			}
			else /*provided*/
				current_address=address;
		}
		/*set address of row*/
		gtk_tree_store_set(GTK_TREE_STORE(current_code_model),&current_code_iter,ADDR_COL,current_address,-1);
		
		
		
		/*  ATAINTION ,We want label-address pairs so we do not make a table
		 *  instead we use a diffrent efficient method ( setting object data)*/
		gint len;
		if((len=g_utf8_strlen(label,8))!=0) /*label is there*/
		{
			gchar *if_data;
			label[len-1]='\0';
			if_data=g_object_get_data(label_addr_pair,label); /*check label is already there in pair list*/
			if(if_data)
			{
				remove_marker();
				scroll_to_row();
				gsim_message(_("Duplicate label is provided here."),GTK_MESSAGE_ERROR);
				/*free any resources*/
				g_object_unref(label_addr_pair);
				gsim_label_address=NULL;
				g_free(address);
				g_free(mne);
				g_free(op1);
				g_free(op2);
				g_free(label);
				g_free(if_data);
				return;
			}
			gchar *data=g_strndup(current_address,5);
			g_object_set_data(label_addr_pair,label,data); /*add a pair in the list*/
			g_free(if_data);
		}
			
		
		
		/*update current address*/
		gint x,i;
		x=make_int__(current_address);
		
		for(i=0;i<80;i++) /*find the matching entry from the table*/
			if(g_ascii_strncasecmp(mne,memfill_call_table[i].mnemonic,5)==0)
				break;

	
		x+=memfill_call_table[i].n_bytes; /*update address*/
		current_address=make_str__(x,4);
	
		/*free any resources*/
		g_free(address);
		g_free(mne);
		g_free(op1);
		g_free(op2);
		g_free(label);
	}
	save_state=1;
	gsim_update_statusbar(FILE_SBAR,filename);
	
	/************** Here actualy the memory is filled with code ***************/
	for(is_iter=gtk_tree_model_get_iter_first(current_code_model,&current_code_iter); is_iter ;
									is_iter=gtk_tree_model_iter_next(current_code_model,&current_code_iter))
	{
		/*get the line data*/
		gtk_tree_model_get(current_code_model,&current_code_iter,ADDR_COL,&address,
											MNE_COL,&mne,OP1_COL,&op1,OP2_COL,&op2,-1);
		
		/*line is empty means new section is started*/
		if(!mne)
		{
			current_address=NULL;
			g_free(address);
			g_free(mne);
			g_free(op1);
			g_free(op2);
			continue;
		}
		
		/*set codeview marker*/
		remove_marker();
		scroll_to_row();
		gtk_tree_selection_select_iter(current_code_selection,&current_code_iter);
		
		/*Find a matching entry in the table and call corrsponding function*/
		gint j;
		for(j=0;j<80;j++)
			if(!g_ascii_strcasecmp(mne,memfill_call_table[j].mnemonic))
				break;
			
		if((*memfill_call_table[j].func)()) /*call the appropriate function*/
		{
			gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(gsim_progress),0);
			return;                          /*return if errer*/
		}
		called_again=0;                      /*************/
		
		/*pulse the progressbar*/
		gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(gsim_progress),1);
		while(gtk_events_pending())
			gtk_main_iteration();
		gfloat delay;
		for(delay=0;delay<2000000;delay++);
			
		gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(gsim_progress),0);
		while(gtk_events_pending())
			gtk_main_iteration();
		for(delay=0;delay<2000000;delay++);
			
		/*free strings*/
		g_free(address);
		g_free(mne);
		g_free(op1);
		g_free(op2);
	}
	
	gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(gsim_progress),0);
	gsim_update_statusbar(DESC_SBAR,_("Code writen to memory successfully"));
	g_object_unref(label_addr_pair);
	gsim_label_address=NULL;
	return;
}
